package com.niiwoo.civet.trade.service.dubbo.invest;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.fastjson.JSON;
import com.niiwoo.activity.stage.dto.response.prize.InvestorExtraDetailDTO;
import com.niiwoo.activity.stage.service.prize.ActivityPrizeDubboService;
import com.niiwoo.civet.trade.constant.enums.ReceivedStatusEnum;
import com.niiwoo.civet.trade.dao.entity.Project;
import com.niiwoo.civet.trade.dao.entity.ProjectInvestOrder;
import com.niiwoo.civet.trade.dao.entity.ProjectInvestorPlan;
import com.niiwoo.civet.trade.dao.mapper.ProjectInvestOrderMapperExt;
import com.niiwoo.civet.trade.dao.mapper.ProjectInvestorPlanMapperExt;
import com.niiwoo.civet.trade.dao.mapper.ProjectMapperExt;
import com.niiwoo.civet.trade.dto.response.InvestOrderDetailDubboDTO;
import com.niiwoo.civet.trade.dto.response.customsystem.QueryProjectInvestOrderResponseDTO;
import com.niiwoo.civet.trade.enums.ProjectInvestOrderEvolutionStatusEnum;
import com.niiwoo.civet.trade.enums.ProjectSubStatusEnum;
import com.niiwoo.civet.trade.enums.RepaymentTypeEnum;
import com.niiwoo.civet.trade.service.invest.InvestOrderDetailDubboService;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by huangmin on 2017/12/10.
 */
@Service(version = "1.0.0")
@Slf4j
public class InvestOrderDetailDubboServiceImpl implements InvestOrderDetailDubboService {

	@Autowired
	private ProjectInvestorPlanMapperExt projectInvestorPlanMapperExt;

	@Autowired
	private ProjectInvestOrderMapperExt projectInvestOrderMapperExt;

	@Autowired
	private ProjectMapperExt projectMapperExt;

	@Reference(version = "1.0.0")
	private ActivityPrizeDubboService activityPrizeDubboService;

	private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

	@Override
	public InvestOrderDetailDubboDTO getInvestOrderDetail(Long investOrderId) {
		ProjectInvestOrder order = projectInvestOrderMapperExt.selectByPrimaryKey(investOrderId);
		InvestOrderDetailDubboDTO result = new InvestOrderDetailDubboDTO();
		result.setEvolutionStatus(order.getEvolutionStatus());
		result.setDeadlineUnit(order.getDeadlineUnit());

		if (ProjectInvestOrderEvolutionStatusEnum.INVESTING.getValue().equals(order.getEvolutionStatus())) {//投资中
			this.completeInvestingOrderDetailDTO(result, order);
		} else if (ProjectInvestOrderEvolutionStatusEnum.BACKING.getValue().equals(order.getEvolutionStatus())
				|| ProjectInvestOrderEvolutionStatusEnum.BACKING_OVERDUE.getValue().equals(order.getEvolutionStatus())) {//回款中的订单
			if (Byte.valueOf("1").equals(order.getDeadlineUnit())) {//按月
				this.completeMonthProjectBackingOrderDetailDTO(result, order);
			} else {//按天
				this.completeDayProjectBackingOrderDetailDTO(result, order);
			}
		} else if (ProjectInvestOrderEvolutionStatusEnum.ALL_BACKED.getValue().equals(order.getEvolutionStatus())) {
			if (Byte.valueOf("1").equals(order.getDeadlineUnit())) {//按月
				this.completeMonthProjectBackedOrderDetailDTO(result, order);
			} else {
				this.completeDayProjectBackedOrderDetailDTO(result, order);
			}
		}
		return result;
	}

	@Override
	public QueryProjectInvestOrderResponseDTO queryLastInvestOrderByUserId(String userId) {
		ProjectInvestOrder projectInvestOrder=projectInvestOrderMapperExt.selectLastOneSuccessByUserId(userId);
		QueryProjectInvestOrderResponseDTO queryProjectInvestOrderResponseDTO=null;
		if(projectInvestOrder!=null){
			queryProjectInvestOrderResponseDTO=new QueryProjectInvestOrderResponseDTO();
			queryProjectInvestOrderResponseDTO.setInvestAmount(projectInvestOrder.getAmount());
			queryProjectInvestOrderResponseDTO.setInvestTime(projectInvestOrder.getCreateTime());
		}

		return queryProjectInvestOrderResponseDTO;
	}

	@Override
	public BigDecimal queryTotalInvestSuccessAmount(String userId) {
		return projectInvestOrderMapperExt.selectTotalInvestSuccessAmountByUserId(userId);
	}

	/**
	 * 完善天标&&已结清的投资订单详情
	 *
	 * @param result
	 * @param order
	 */
	private void completeDayProjectBackedOrderDetailDTO(InvestOrderDetailDubboDTO result, ProjectInvestOrder order) {
		InvestOrderDetailDubboDTO.DayProjectBackedOrderDetailDTO dayProjectBackedOrderDetailDTO = new InvestOrderDetailDubboDTO.DayProjectBackedOrderDetailDTO();
		AddInterestDTO addInterestDTO = this.getAddInterestDTO(order);
		BigDecimal backedAddInterest = addInterestDTO.getBackedAddInterest();// 已回加息
		BigDecimal backingAddInterest = addInterestDTO.getBackingAddInterest();// 已回加息

		List<ProjectInvestorPlan> projectInvestorPlans = projectInvestorPlanMapperExt.listByInvestOrder(order.getId());
		//天标，只存在一期
		ProjectInvestorPlan projectInvestorPlan = projectInvestorPlans.get(0);
		if (ReceivedStatusEnum.INIT.getStatus().equals(projectInvestorPlan.getReceivedStatus())) {//回款计划为未回款状态

		}
		dayProjectBackedOrderDetailDTO.setAmount(order.getAmount());
		dayProjectBackedOrderDetailDTO.setInterestTotal(projectInvestorPlan.getReceivedInterest().add(backedAddInterest));
		dayProjectBackedOrderDetailDTO.setInterest(projectInvestorPlan.getReceivedInterest());
		dayProjectBackedOrderDetailDTO.setBackDate(sdf.format(projectInvestorPlan.getReceivedDate()));
		dayProjectBackedOrderDetailDTO.setAddInterest(backingAddInterest.add(backedAddInterest));
		dayProjectBackedOrderDetailDTO.setRepaymentType(RepaymentTypeEnum.enumOf(order.getRepaymentType()).getDesc());
		Project project = projectMapperExt.selectByUserIdAndProjectId(order.getBorrowUserId(), order.getProjectId());
		dayProjectBackedOrderDetailDTO.setStatus(this.formatStatus(projectInvestorPlan.getReceivedStatus(), project.getSubStatus(), projectInvestorPlan.getReceivedDate(), projectInvestorPlan.getIsGuarantee()));
		result.setDayProjectBackedOrderDetailDTO(dayProjectBackedOrderDetailDTO);
	}


	/**
	 * 完善天标&&回款中的投资订单详情
	 *
	 * @param result
	 * @param order
	 */
	private void completeDayProjectBackingOrderDetailDTO(InvestOrderDetailDubboDTO result, ProjectInvestOrder order) {
		InvestOrderDetailDubboDTO.DayProjectBackingOrderDetailDTO dayProjectBackingOrderDetailDTO = new InvestOrderDetailDubboDTO.DayProjectBackingOrderDetailDTO();
		AddInterestDTO addInterestDTO = this.getAddInterestDTO(order);
		BigDecimal backedAddInterest = addInterestDTO.getBackedAddInterest();// 已回加息
		BigDecimal backingAddInterest = addInterestDTO.getBackingAddInterest();//待加息

		BigDecimal backingCapitalAndInterest = BigDecimal.ZERO;//待回本息
		List<ProjectInvestorPlan> projectInvestorPlans = projectInvestorPlanMapperExt.listByInvestOrder(order.getId());
		//天标，只存在一期
		ProjectInvestorPlan projectInvestorPlan = projectInvestorPlans.get(0);
		if (ReceivedStatusEnum.INIT.getStatus().equals(projectInvestorPlan.getReceivedStatus())) {//回款计划为未回款状态
			backingCapitalAndInterest = backingCapitalAndInterest
					.add(projectInvestorPlan.getCapital())
					.add(projectInvestorPlan.getInterest())
					.subtract(projectInvestorPlan.getReceivedCapital())
					.subtract(projectInvestorPlan.getReceivedInterest());
		}
		dayProjectBackingOrderDetailDTO.setBackingAmount(backingCapitalAndInterest.add(backingAddInterest));
		dayProjectBackingOrderDetailDTO.setBackedAmount(projectInvestorPlan.getReceivedCapital().add(projectInvestorPlan.getReceivedInterest()).add(backedAddInterest));
		dayProjectBackingOrderDetailDTO.setDeadline(String.valueOf(order.getDeadline()));
		dayProjectBackingOrderDetailDTO.setAmount(order.getAmount());
		dayProjectBackingOrderDetailDTO.setInterest(order.getInterest().add(order.getAddInterest()));
		dayProjectBackingOrderDetailDTO.setBackDate(sdf.format(projectInvestorPlan.getReceivedDate()));
		dayProjectBackingOrderDetailDTO.setAddInterest(backedAddInterest.add(backingAddInterest));
		dayProjectBackingOrderDetailDTO.setRepaymentType(RepaymentTypeEnum.enumOf(order.getRepaymentType()).getDesc());
		Project project = projectMapperExt.selectByUserIdAndProjectId(order.getBorrowUserId(), order.getProjectId());
		dayProjectBackingOrderDetailDTO.setStatus(this.formatStatus(projectInvestorPlan.getReceivedStatus(), project.getSubStatus(), projectInvestorPlan.getReceivedDate(), projectInvestorPlan.getIsGuarantee()));
		result.setDayProjectBackingOrderDetailDTO(dayProjectBackingOrderDetailDTO);
	}

	/**
	 * 完善月标&&回款中的投资订单详情
	 *
	 * @param result
	 * @param order
	 */
	private void completeMonthProjectBackingOrderDetailDTO(InvestOrderDetailDubboDTO result, ProjectInvestOrder order) {
		InvestOrderDetailDubboDTO.MonthProjectBackingOrderDetailDTO monthProjectBackingOrderDetailDTO = new InvestOrderDetailDubboDTO.MonthProjectBackingOrderDetailDTO();
		// 处理加息
		AddInterestDTO addInterestDTO = this.getAddInterestDTO(order);
		BigDecimal backedAddInterest = addInterestDTO.getBackedAddInterest();// 已回加息
		BigDecimal backingAddInterest = addInterestDTO.getBackingAddInterest();//待加息
		Integer currentPeriod = 0;
		BigDecimal backedCapitalAndInterest = BigDecimal.ZERO; //已回本息
		BigDecimal backingCapitalAndInterest = BigDecimal.ZERO;// 待回本息
		List<ProjectInvestorPlan> projectInvestorPlans = projectInvestorPlanMapperExt.listByInvestOrder(order.getId());
		Project project = projectMapperExt.selectByUserIdAndProjectId(order.getBorrowUserId(), order.getProjectId());
		for (ProjectInvestorPlan projectInvestorPlan : projectInvestorPlans) {
			if (!ReceivedStatusEnum.INIT.getStatus().equals(projectInvestorPlan.getReceivedStatus())) {//如果回款计划标识为未收款，
				currentPeriod = projectInvestorPlan.getCurrentPeriod();//本期数即为当前回款期数
			}
			//已收本息=已收本金+已收利息
			backedCapitalAndInterest = backedCapitalAndInterest
					.add(projectInvestorPlan.getReceivedCapital())
					.add(projectInvestorPlan.getReceivedInterest());
			//回款计划为未回款状态
			if (ReceivedStatusEnum.INIT.getStatus().equals(projectInvestorPlan.getReceivedStatus())) {
				backingCapitalAndInterest = backingCapitalAndInterest.add(projectInvestorPlan.getCapital())
						.add(projectInvestorPlan.getInterest())
						.subtract(projectInvestorPlan.getReceivedCapital())
						.subtract(projectInvestorPlan.getReceivedInterest());
			}
			InvestOrderDetailDubboDTO.BackPlanDTO backPlanDTO = new InvestOrderDetailDubboDTO.BackPlanDTO();
			BigDecimal addInterestPeriod = addInterestDTO.getAddInterestMap().get(projectInvestorPlan.getCurrentPeriod());
			backPlanDTO.setAddInterest(null == addInterestPeriod ? BigDecimal.ZERO.setScale(2) : addInterestPeriod);
			backPlanDTO.setAmount(projectInvestorPlan.getCapital());
			backPlanDTO.setBackDate(sdf.format(projectInvestorPlan.getReceivedDate()));
			if (ReceivedStatusEnum.INIT.getStatus().equals(projectInvestorPlan.getReceivedStatus())) {
				backPlanDTO.setInterest(projectInvestorPlan.getInterest());
			} else {
				backPlanDTO.setInterest(projectInvestorPlan.getReceivedInterest());
			}
			backPlanDTO.setPeriod("第" + projectInvestorPlan.getCurrentPeriod() + "/" + order.getDeadline() + "期");
			backPlanDTO.setStatus(this.formatStatus(projectInvestorPlan.getReceivedStatus(), project.getSubStatus(), projectInvestorPlan.getReceivedDate(), projectInvestorPlan.getIsGuarantee()));
			monthProjectBackingOrderDetailDTO.getBackPlanDTOList().add(backPlanDTO);
		}
		if (order.getAddInterest().compareTo(BigDecimal.ZERO) > 0) {
			monthProjectBackingOrderDetailDTO.setHaveAddInterest(Byte.valueOf("1"));
		}
		monthProjectBackingOrderDetailDTO.setBackingAmount(backingCapitalAndInterest.add(backingAddInterest));
		monthProjectBackingOrderDetailDTO.setBackedAmount(backedCapitalAndInterest.add(backedAddInterest));
		monthProjectBackingOrderDetailDTO.setBackedPeriod(String.valueOf(currentPeriod));
		monthProjectBackingOrderDetailDTO.setAmount(order.getAmount());
		monthProjectBackingOrderDetailDTO.setInterest(order.getInterest().add(order.getAddInterest()));
		monthProjectBackingOrderDetailDTO.setTotalPeriods(order.getDeadline());
		monthProjectBackingOrderDetailDTO.setRepaymentType(RepaymentTypeEnum.enumOf(order.getRepaymentType()).getDesc());
		result.setMonthProjectBackingOrderDetailDTO(monthProjectBackingOrderDetailDTO);
	}

	/**
	 * 状态转换
	 *
	 * @param receivedStatus   入参：收款状态(1未收款，2正常收款，3逾期收款，4已提前结清)
	 * @param projectSubStatus
	 * @param receivedDate
	 * @param isGuarantee
	 * @return 收款状态(1回款中，2回款逾期，3已回款，4提前结清, 5第三方担保机构代偿)
	 */
	private Byte formatStatus(Byte receivedStatus, Integer projectSubStatus, Date receivedDate, Byte isGuarantee) {
		if (Byte.valueOf("2").equals(receivedStatus) || Byte.valueOf("3").equals(receivedStatus)) {
			if (Byte.valueOf("1").equals(isGuarantee)) {
				return Byte.valueOf("5");
			} else {
				return Byte.valueOf("3");
			}
		} else if (Byte.valueOf("4").equals(receivedStatus)) {
			return Byte.valueOf("4");
		} else {
			Date now = new Date();
			if ((ProjectSubStatusEnum.REPAYING_OVERDUE.getSubStatus() == projectSubStatus
					|| ProjectSubStatusEnum.REPAYING_BAD.getSubStatus() == projectSubStatus)
					&& new DateTime(receivedDate).plusDays(1).toDate().before(now)) {
				return Byte.valueOf("2");
			} else {
				return Byte.valueOf("1");
			}
		}
	}

	/**
	 * 完善月标&&已结清的投资订单详情
	 *
	 * @param result
	 * @param order
	 */
	private void completeMonthProjectBackedOrderDetailDTO(InvestOrderDetailDubboDTO result, ProjectInvestOrder order) {
		InvestOrderDetailDubboDTO.MonthProjectBackedOrderDetailDTO monthProjectBackedOrderDetailDTO = new InvestOrderDetailDubboDTO.MonthProjectBackedOrderDetailDTO();
		// 处理加息
		AddInterestDTO addInterestDTO = this.getAddInterestDTO(order);
		BigDecimal backedAddInterest = addInterestDTO.getBackedAddInterest();// 已回加息
		BigDecimal backedInterest = BigDecimal.ZERO; //已回利息
		List<ProjectInvestorPlan> projectInvestorPlans = projectInvestorPlanMapperExt.listByInvestOrder(order.getId());
		Project project = projectMapperExt.selectByUserIdAndProjectId(order.getBorrowUserId(), order.getProjectId());
		for (ProjectInvestorPlan projectInvestorPlan : projectInvestorPlans) {
			backedInterest = backedInterest.add(projectInvestorPlan.getReceivedInterest());

			InvestOrderDetailDubboDTO.BackPlanDTO backPlanDTO = new InvestOrderDetailDubboDTO.BackPlanDTO();
			BigDecimal addInterestPeriod = addInterestDTO.getAddInterestMap().get(projectInvestorPlan.getCurrentPeriod());
			backPlanDTO.setAddInterest(null == addInterestPeriod ? BigDecimal.ZERO.setScale(2) : addInterestPeriod);
			backPlanDTO.setAmount(projectInvestorPlan.getCapital());
			backPlanDTO.setBackDate(sdf.format(projectInvestorPlan.getReceivedDate()));
			backPlanDTO.setInterest(projectInvestorPlan.getReceivedInterest());
			backPlanDTO.setPeriod("第" + projectInvestorPlan.getCurrentPeriod() + "/" + order.getDeadline() + "期");
			backPlanDTO.setStatus(this.formatStatus(projectInvestorPlan.getReceivedStatus(), project.getSubStatus(), projectInvestorPlan.getReceivedDate(), projectInvestorPlan.getIsGuarantee()));
			monthProjectBackedOrderDetailDTO.getBackPlanDTOList().add(backPlanDTO);
		}
		if (order.getAddInterest().compareTo(BigDecimal.ZERO) > 0) {
			monthProjectBackedOrderDetailDTO.setHaveAddInterest(Byte.valueOf("1"));
		}
		monthProjectBackedOrderDetailDTO.setAmount(order.getAmount());
		monthProjectBackedOrderDetailDTO.setInterest(backedInterest.add(backedAddInterest));
		monthProjectBackedOrderDetailDTO.setTotalPeriods(order.getDeadline());
		monthProjectBackedOrderDetailDTO.setRepaymentType(RepaymentTypeEnum.enumOf(order.getRepaymentType()).getDesc());
		result.setMonthProjectBackedOrderDetailDTO(monthProjectBackedOrderDetailDTO);
	}

	/**
	 * 完善投资中的投资订单详情
	 *
	 * @param result
	 * @param order
	 */
	private void completeInvestingOrderDetailDTO(InvestOrderDetailDubboDTO result, ProjectInvestOrder order) {
		InvestOrderDetailDubboDTO.InvestingOrderDetailDTO investingOrderDetailDTO = new InvestOrderDetailDubboDTO.InvestingOrderDetailDTO();
		investingOrderDetailDTO.setAmount(order.getAmount());//投资总金额
		investingOrderDetailDTO.setInterest(order.getInterest().add(order.getAddInterest()));// 需要加息
		investingOrderDetailDTO.setContractAmount(order.getContractAmount());//
		BigDecimal investedAmount = projectInvestOrderMapperExt.selectInvestedAmount(order.getProjectId());//已投资金额
		investingOrderDetailDTO.setInvestedAmount(investedAmount);
		Project project = projectMapperExt.selectByUserIdAndProjectId(order.getBorrowUserId(), order.getProjectId());
		investingOrderDetailDTO.setInvestEndTime(project.getInvestEndTime());
		if (investedAmount.compareTo(order.getContractAmount()) == 0) {//如果已投金额等于借款目标,则说明已满标
			investingOrderDetailDTO.setIsFull(Byte.valueOf("1"));
		}
		//增加投资结束时间
		investingOrderDetailDTO.setInvestEndTime(project.getInvestEndTime());
		investingOrderDetailDTO.setDesc("该项目正在筹款中");
		result.setInvestingOrderDetailDTO(investingOrderDetailDTO);
	}

	/**
	 * 获取加息模型
	 *
	 * @param order
	 * @return
	 */
	private AddInterestDTO getAddInterestDTO(ProjectInvestOrder order) {
		AddInterestDTO result = new AddInterestDTO();
		// 处理加息
		BigDecimal addInterest = BigDecimal.ZERO;// 总加息
		BigDecimal backedAddInterest = BigDecimal.ZERO;// 已回加息
		if (null != order.getPrizeId() && Byte.valueOf("8").equals(order.getPrizeTypteId())) {
			List<InvestorExtraDetailDTO> investorExtralDtlSingle = null;
			try {
				investorExtralDtlSingle = activityPrizeDubboService.getInvestorExtralDtlSingle(order.getPrizeId());
				log.info("获取加息券信息:" + JSON.toJSONString(investorExtralDtlSingle));
			} catch (Exception e) {
				log.error("无法获取加息券信息，prizeId=" + order.getPrizeId(), e);
			}

			if (null != investorExtralDtlSingle) {
				for (InvestorExtraDetailDTO investorExtraDetailDTO : investorExtralDtlSingle) {
					// 加息回款状态 0：未回款 1：已作废 2：已回款
					Byte status = investorExtraDetailDTO.getStatus();
					if (!Byte.valueOf("1").equals(status)) {
						addInterest = addInterest.add(investorExtraDetailDTO.getExtraAmount());
						result.getAddInterestMap().put(investorExtraDetailDTO.getCurrPeriods(), investorExtraDetailDTO.getExtraAmount());
						if (Byte.valueOf("2").equals(status)) {
							backedAddInterest = backedAddInterest.add(investorExtraDetailDTO.getExtraAmount());
						}
					}
				}
			}
		}
		BigDecimal backingAddInterest = addInterest.subtract(backedAddInterest);//待加息 = 总加息 - 已回加息
		result.setBackedAddInterest(backedAddInterest);
		result.setBackingAddInterest(backingAddInterest);
		return result;
	}

	/**
	 * 加息模型
	 */
	@Data
	private static class AddInterestDTO {
		private BigDecimal backedAddInterest;// 已回加息
		private Map<Integer, BigDecimal> addInterestMap = new HashMap<>();// 加息列表
		private BigDecimal backingAddInterest;// 待回加息
	}

}
